// Aleth: Ethereum C++ client, tools and libraries.
// Copyright 2015-2019 Aleth Authors.
// Licensed under the GNU General Public License, Version 3.

#include <json/writer.h>
#include <libethashseal/Ethash.h>
#include <libethereum/BlockChain.h>
#include "BlockChainLoader.h"
#include "Common.h"
using namespace std;
using namespace dev;
using namespace dev::test;
using namespace dev::eth;

BlockChainLoader::BlockChainLoader(Json::Value const& _json, eth::Network _sealEngineNetwork):
	m_block(Block::Null)
{
	// load genesisBlock
    Json::FastWriter a;
    bytes genesisBlock = fromHex(_json["genesisRLP"].asString());
    ChainParams params(
        genesisInfo(_sealEngineNetwork), genesisBlock, jsonToAccountMap(a.write(_json["pre"])));
    if (_json.isMember("sealEngine"))
    {
        if (_json["sealEngine"].asString() == eth::NoProof::name())
            params.sealEngineName = eth::NoProof::name();
        else if (_json["sealEngine"].asString() == eth::Ethash::name())
            params.sealEngineName = eth::Ethash::name();
    }
    m_bc.reset(new BlockChain(params, m_dir.path(), WithExisting::Kill));

    // load pre state
    m_block = m_bc->genesisBlock(State::openDB(m_dir.path(), m_bc->genesisHash(), WithExisting::Kill));

	assert(m_block.rootHash() == m_bc->info().stateRoot());

	// load blocks
	for (auto const& block: _json["blocks"])
	{
		bytes rlp = fromHex(block["rlp"].asString());
		m_bc->import(rlp, state().db());
	}

	// sync state
	m_block.sync(*m_bc);
}
